# -*- coding:utf-8 -*-

import fnmatch

from ConfigReader import ConfigReader
from ConfigInfo import RuleInfo
from MyPrint import print_green_line
from MyPrint import print_yellow_line

#定义应用配置文件助手
class ConfigAssist:
    def __init__(self):
        """
        初始化
        """
        self.config_reader = ConfigReader()
        
    def search_ftp_info(self, ftp_name):
        """
        在所有配置文件中查询FTP发送接口信息，如果在多个应用配置文件中发现该FTP接口信息，提示选择
        @param ftp_name: 需要查找的FTP接口名
        @return: FTP接口全局名称列表
        """
        #读取应用配置文件，获取FTP配置
        all_app_conf = self.config_reader.read_all_app_conf()
        ftp_client_list = all_app_conf.ftp_unit_list

        #检查需要统计的FTP发送接口是否在配置文件中
        ftp_name_list = []
        for ftp_client in ftp_client_list:
            if ftp_client.name[ftp_client.name.find("FTP_"):] == ftp_name:
                ftp_name_list.append(ftp_client.name)
        
        #没有发现FTP发送接口
        if not ftp_name_list:
            print_yellow_line("应用配置文件中没有发现FTP接口 %s 的配置信息！"%(ftp_name))
            return ftp_name_list
#            PrintGREEN("配置文件中没有发现FTP接口 %s 的配置信息！"%(ftp_name))
            
        #发现多个FTP接口，请用户选择
        if len(ftp_name_list) > 1:
            print_green_line("在以下应用配置文件中发现FTP接口 %s 的配置信息\n请输入序号选择您所使用的配置文件\n"%(ftp_name))
            
            for i in range(len(ftp_name_list)):
                print_green_line(str(i) + "\t" + ftp_name_list[i][0:ftp_name_list[i].find("_FTP_")] + ".conf")
            print_green_line(str(len(ftp_name_list)) + "\t选择所有")
            
            #获取键盘输入    
            input = 0
            while(True):
                input = raw_input()
                if input.isdigit():
                    input = int(input)
                    if input < len(ftp_name_list) and input >= 0:
                        ftp_name_list = [ftp_name_list[input]]
                        break
                    if input == len(ftp_name_list):
                        break
                print_yellow_line("输入无效!")
        
        return ftp_name_list
        
    def search_path_info(self, path_name):
        """
        在所有配置文件中查询PATH拷贝接口信息，如果在多个应用配置文件中发现该PATH接口信息，提示选择
        @param path_name: 需要查找的PATH接口名
        @return: PATH接口全局名称列表
        """
        #读取配置文件
        all_app_conf = self.config_reader.read_all_app_conf()
        path_client_list = all_app_conf.path_unit_list
        
        #查看PATH接口是否在配置文件中
        path_name_list = []
        for path_client in path_client_list:
            if path_client.name[path_client.name.find("PATH_"):] == path_name:
                path_name_list.append(path_client.name)
        
        #没有发现本地拷贝接口
        if not path_name_list:
            print_yellow_line("应用配置文件中没有发现PATH接口 %s 的配置信息！"%(path_name))
            return path_name_list
#            PrintGREEN("配置文件中没有发现PATH接口 %s 的配置信息！"%(path_name))
          
        #用户选择所需的配置文件  
        if len(path_name_list) > 1:
            print_green_line("在以下配置文件中发现PATH接口 %s 的配置信息\n请输入序号选择您所使用的配置文件\n"%(path_name))
            for i in range(len(path_name_list)):
                print_green_line(str(i) + "\t" + path_name_list[i][0:path_name_list[i].find("_PATH_")] + ".conf")
            print_green_line(str(len(path_name_list)) + "\t选择所有")
            
            #获取键盘输入    
            input = 0
            while(True):
                input = raw_input()
                if input.isdigit():
                    input = int(input)
                    if input < len(path_name_list) and input >= 0:
                        path_name_list = [path_name_list[input]]
                        break
                    if input == len(path_name_list):
                        break
                print_yellow_line("输入无效!")
        
        return path_name_list
    
    def check_match_rule(self, all_app_conf=None):
        """
        检查匹配规则之间的包含关系，并去除无效的匹配规则
        @param all_app_conf: 所有应用配置文件信息
        """
        result = ""
        
        #没有应用配置文件信息需要从配置文件中读取
        if not all_app_conf:
            all_app_conf = self.config_reader.read_all_app_conf()
            #all_app_conf.show()
        #按照发送接口分组一般匹配规则
        unit_name_map = {}
        for match_rule in all_app_conf.match_rule_list:
            for ftp_name in match_rule.ftp_list:
                if ftp_name in unit_name_map:
                    unit_name_map[ftp_name].append(match_rule.rule)
                else:
                    unit_name_map[ftp_name]= [match_rule.rule]
            for path_name in match_rule.path_list:
                if path_name in unit_name_map:
                    unit_name_map[path_name].append(match_rule.rule)
                else:
                    unit_name_map[path_name] = [match_rule.rule]

        #检查每个发送接口的包含关系
        for unit_name in unit_name_map:
            rule_list = unit_name_map[unit_name]
            rule_num = len(rule_list)
            for i in range(rule_num):
                tmp_rule = rule_list.pop(0)
                for rule in rule_list:
                    if fnmatch.fnmatch(tmp_rule, rule):
                        if unit_name.find("FTP_") > 0:
                            config = unit_name[:unit_name.find("_FTP_")] + ".conf"
                            section = unit_name[unit_name.find("FTP_"):]
                        else:
                            config = unit_name[:unit_name.find("_PATH_")] + ".conf"
                            section = unit_name[unit_name.find("PATH_"):]
                        result += "应用配置文件 %s 中 %s 接口匹配规则 %s 包含 %s\n"%(config, section, rule, tmp_rule)
                        break
                else:
                    rule_list.append(tmp_rule)
            
        #按发送接口分组否定匹配规则
        no_unit_name_map = {}
        for nomatch_rule in all_app_conf.nomatch_rule_list:
            for ftp_name in nomatch_rule.ftp_list:
                if ftp_name in no_unit_name_map:
                    no_unit_name_map[ftp_name].append(nomatch_rule.rule)
                else:
                    no_unit_name_map[ftp_name] = [nomatch_rule.rule]
            for path_name in nomatch_rule.path_list:
                if path_name in no_unit_name_map:
                    no_unit_name_map[path_name].append(nomatch_rule.rule)
                else:
                    no_unit_name_map[path_name] = [nomatch_rule.rule]
       
        #检查一般匹配规则与否定匹配规则之间的包含关系
        for unit_name in no_unit_name_map:
            no_rule_list = no_unit_name_map[unit_name]
            no_rule_num = len(no_rule_list)
            if unit_name in unit_name_map:
                rule_list = unit_name_map[unit_name]
                for i in range(no_rule_num):
                    tmp_rule = no_rule_list.pop(0)
                    for rule in rule_list:
                        if fnmatch.fnmatch(tmp_rule, rule):
                            no_rule_list.append(tmp_rule)
                            break
                    else:
                        if unit_name.find("FTP_") > 0:
                            config = unit_name[:unit_name.find("_FTP_")] + ".conf"
                            section = unit_name[unit_name.find("FTP_"):]
                        else:
                            config = unit_name[:unit_name.find("_PATH_")] + ".conf"
                            section = unit_name[unit_name.find("PATh_"):]
                        result += "应用配置文件 %s 中 %s 接口存在无效的否定匹配 %s\n"%(config ,section, tmp_rule)
            else:
                if unit_name.find("FTP_") > 0:
                    config = unit_name[:unit_name.find("_FTP_")] + ".conf"
                    section = unit_name[unit_name.find("FTP_"):]
                else:
                    config = unit_name[:unit_name.find("_PATH_")] + ".conf"
                    section = unit_name[unit_name.find("PATh_"):]
                for i in range(len(no_rule_list)):
                    result += "应用配置文件 %s 中 %s 接口存在无效的否定匹配 %s\n"%(config ,section, no_rule_list.pop())
       
        #检查否定匹配规则之间的包含关系
        for unit_name in no_unit_name_map:
            rule_list = no_unit_name_map[unit_name]
            rule_num = len(rule_list)
            for i in range(rule_num):
                tmp_rule = rule_list.pop(0)
                for rule in rule_list:
                    if fnmatch.fnmatch(tmp_rule, rule):
                        if unit_name.find("FTP_") > 0:
                            config = unit_name[:unit_name.find("_FTP_")] + ".conf"
                            section = unit_name[unit_name.find("FTP_"):]
                        else:
                            config = unit_name[:unit_name.find("_PATH_")] + ".conf"
                            section = unit_name[unit_name.find("PATh_"):]
                        result += "应用配置文件 %s 中 %s 接口匹配规则 %s 包含 %s\n"%(config, section, rule, tmp_rule)
                        break
                else:
                    rule_list.append(tmp_rule)            

        #重新生成一般匹配规则
        all_app_conf.match_rule_list = []
        for unit_name in unit_name_map:
            rule_list = unit_name_map[unit_name]
            for rule in rule_list:
                for match_rule in all_app_conf.match_rule_list:
                    if match_rule.rule == rule:
                        if unit_name.find("_FTP_") > -1:
                            match_rule.ftp_list.append(unit_name)
                        else:
                            match_rule.path_list.append(unit_name)
                        break
                else:
                    match_rule = RuleInfo()
                    match_rule.rule = rule
                    if unit_name.find("_FTP_") > -1:
                        match_rule.ftp_list.append(unit_name)
                    else:
                        match_rule.path_list.append(unit_name)  
                    all_app_conf.match_rule_list.append(match_rule)

        #重新生成否定匹配规则
        all_app_conf.nomatch_rule_list = []
        for unit_name in no_unit_name_map:
            rule_list = no_unit_name_map[unit_name]
            for rule in rule_list:
                for match_rule in all_app_conf.nomatch_rule_list:
                    if match_rule.rule == rule:
                        if unit_name.find("_FTP_") > -1:
                            match_rule.ftp_list.append(unit_name)
                        else:
                            match_rule.path_list.append(unit_name)
                        break
                else:
                    match_rule = RuleInfo()
                    match_rule.rule = rule
                    if unit_name.find("_FTP_") > -1:
                        match_rule.ftp_list.append(unit_name)
                    else:
                        match_rule.path_list.append(unit_name)  
                    all_app_conf.nomatch_rule_list.append(match_rule) 
                    
        return all_app_conf, result              
